package com.loongtech.bi.manager.player;

import com.loongtech.bi.manager.game.NewRoleSchoolSecondLostLevelDistributeManager;
import com.loongtech.bi.manager.game.NewUser1LevelDistributeManager;
import com.loongtech.bi.manager.game.UserSecondLoss1LevelDistributeManager;
import com.loongtech.bi.manager.game.UserThirdLoss1LevelDistributeManager;
import com.loongtech.bi.manager.system.GameParamConfigManager;
import com.loongtech.bi.support.CommonGameParam;
import com.loongtech.bi.support.chart.ChartData1;
import com.loongtech.bi.support.chart.ChartFlow;
import com.loongtech.bi.support.chart.ChartSelect;
import com.loongtech.core.jpa.manager.ManagerQueryCacheBase;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * 玩家分析-留存分析manager
 * 
 * @author marin
 * @date 2015-09-15
 */
@Service
public class LostPlayerManager extends ManagerQueryCacheBase<Object> {
	private static final long serialVersionUID = 1L;
	
	@Autowired
	private NewUserManager newUserManager;
	@Autowired
	private UserThirdLossManager userThirdLossManager;
	@Autowired
	private UserSevenLossManager userSevenLossManager;
	@Autowired
    private UserSecondLoss1LevelDistributeManager userSecondLoss1LevelDistributeManager;
	@Autowired
    private NewUser1LevelDistributeManager newUser1LevelDistributeManager;
    @Autowired
    private UserThirdLoss1LevelDistributeManager userThirdLoss1LevelDistributeManager;
    @Autowired
    private NewRoleSchoolSecondLostLevelDistributeManager newRoleSchoolSecondLostLevelDistributeManager;

	//流失率
	public List<LossPlayerData> getLossPlayerData(Date dateStart, Date dateEnd, String queryPlatform, String queryChannel, String queryServer) {
		List<LossPlayerData> result = new ArrayList<LossPlayerData>();
		//map
		Map<String,LossPlayerData> map = new HashMap<String,LossPlayerData>();
		//新增账号
		List<Object[]> newUserList = newUserManager.getNewUserByAllKind(dateStart, dateEnd, queryPlatform, queryChannel, queryServer);
		
		for(Object[] o : newUserList) {
			LossPlayerData LossPlayerData = new LossPlayerData();
			LossPlayerData.setDay(o[0].toString());
			LossPlayerData.setNewUser(Integer.parseInt(o[1].toString()));
			//map 存入
			map.put(o[0].toString(), LossPlayerData);
		}
		
		//三日
		List <Object[]> list = userThirdLossManager.getUserThirdLossByAllKind(dateStart, dateEnd, queryPlatform, queryChannel, queryServer);
		for(Object[] o : list) {
			LossPlayerData LossPlayerData = map.get(o[0].toString());
			
			if(LossPlayerData != null) {
				LossPlayerData.setUser_third_loss(Float.parseFloat(o[1].toString()));
				
				//map 存入
				map.put(o[0].toString(), LossPlayerData);
			}
		}
		
		//七日
		list = userSevenLossManager.getUserSevenLossByAllKind(dateStart, dateEnd, queryPlatform, queryChannel, queryServer);
		for(Object[] o : list) {
			LossPlayerData LossPlayerData = map.get(o[0].toString());
			
			if(LossPlayerData != null) {
				LossPlayerData.setUser_seven_loss(Float.parseFloat(o[1].toString()));
				
				//map 存入
				map.put(o[0].toString(), LossPlayerData);
			}
		}
		
		//遍历存入结果
		for(Object[] o : newUserList) {
			LossPlayerData LossPlayerData = map.get(o[0].toString());
			
			if(LossPlayerData != null) {
				result.add(LossPlayerData);
			}
		}
		
		return result;
	}
	
	//流失
	public class LossPlayerData {
		private String platformId;
		private String channelId;
		private String serverId;
		@ChartFlow(name="日期")
		private String day; // 日期
		private int newUser; //
		@ChartSelect(name = "新增用户数", key = 1)
		@ChartData1(name = "3日流失率", key = 1)
		private float user_third_loss = 0f; //
		@ChartData1(name = "7日流失率", key = 1)
		private float user_seven_loss = 0f; //
		
		public String getPlatformId() {
			return platformId;
		}
		public void setPlatformId(String platformId) {
			this.platformId = platformId;
		}
		public String getChannelId() {
			return channelId;
		}
		public void setChannelId(String channelId) {
			this.channelId = channelId;
		}
		public String getServerId() {
			return serverId;
		}
		public void setServerId(String serverId) {
			this.serverId = serverId;
		}
		public String getDay() {
			return day;
		}
		public void setDay(String day) {
			this.day = day;
		}
		public int getNewUser() {
			return newUser;
		}
		public void setNewUser(int newUser) {
			this.newUser = newUser;
		}
		public float getUser_third_loss() {
			return user_third_loss;
		}
		public void setUser_third_loss(float user_third_loss) {
			this.user_third_loss = user_third_loss;
		}
		public float getUser_seven_loss() {
			return user_seven_loss;
		}
		public void setUser_seven_loss(float user_seven_loss) {
			this.user_seven_loss = user_seven_loss;
		}
	}

	private List<LossUserData> getLossUserDatas(List<Object[]> sumUserNumberList, List<Object[]> levelList, List<Object[]> okLevelList, String lossType) {
        List<LossUserData> result = new ArrayList<>();

        //总人数
        int sumUserNumber = 0;
        if(sumUserNumberList != null && sumUserNumberList.size() > 0 && sumUserNumberList.get(0)[0] != null) {
            sumUserNumber = Integer.parseInt(sumUserNumberList.get(0)[0].toString());
        }

        // 满足条件的等级人数
        Map<Integer, Integer> okMap = new HashMap<>();
        if (okLevelList != null && okLevelList.size() > 0 && okLevelList.get(0)[0] != null) {
            for(Object[] o : okLevelList) {
                okMap.put(Integer.parseInt(o[0].toString()), Integer.parseInt(o[1].toString()));
            }
        }

        for(Object[] o : levelList) {
            LossUserData u = new LossUserData();
            u.setLevel(Integer.parseInt(o[0].toString()));
            u.setLossType(lossType);
            u.setAllLossUserNum(sumUserNumber);
            u.setLossUserNum(Integer.parseInt(o[1].toString()));
            u.setLossRate(u.getAllLossUserNum() == 0 ? 0 : (float)(u.getLossUserNum() * 1.0 / u.getAllLossUserNum()));
            u.setOkUserNum(okMap.get(u.getLevel()) == null ? 0 : okMap.get(u.getLevel()));
            u.setLevelLossRate(u.getOkUserNum() == 0 ? 0 : (float)(u.getLossUserNum() * 1.0 / u.getOkUserNum()));

            result.add(u);
        }

        return result;
    }

    public List<LossUserData> getLossUserDatas(Date date, String queryPlatform, String queryChannel, String queryServer) {
        List<LossUserData> result = new ArrayList<>();

        List<Object[]> sumUserNumberList = userSecondLoss1LevelDistributeManager.getAllKindUserNumber(date, date, queryPlatform, queryChannel, queryServer);
        List<Object[]> levelList = userSecondLoss1LevelDistributeManager.getAllKindUserNumberGroupByLevel(date, date, queryPlatform, queryChannel, queryServer);
        List<Object[]> okLevelList = newUser1LevelDistributeManager.getAllKindUserNumberGroupByLevel(date, date, queryPlatform, queryChannel, queryServer);
        result.addAll(getLossUserDatas(sumUserNumberList, levelList, okLevelList, "2"));

        sumUserNumberList = userThirdLoss1LevelDistributeManager.getAllKindUserNumber(date, date, queryPlatform, queryChannel, queryServer);
        levelList = userThirdLoss1LevelDistributeManager.getAllKindUserNumberGroupByLevel(date, date, queryPlatform, queryChannel, queryServer);
        //okLevelList = newUser1LevelDistributeManager.getAllKindUserNumberGroupByLevel(date, date, queryPlatform, queryChannel, queryServer);
        result.addAll(getLossUserDatas(sumUserNumberList, levelList, okLevelList, "3"));

        Collections.sort(result, new LossUserData().comparatorLevel);
        return result;
    }

    public class LossUserData {
        @ChartFlow(name = "等级")
        private Integer level;  // 等级
        private String lossType;  // 流失类型：2日，3日
        private int allLossUserNum;  // 所有流失帐户数
        private int lossUserNum;  // 等级流失帐户数
        private int okUserNum;  // 到达等级帐户数
        @ChartSelect(name = "等级流失", key = 1)
        @ChartData1(name = "流失人数占比", key = 1)
        private float lossRate;
        @ChartData1(name = "等级流失率", key = 1)
        private float levelLossRate;

        // 比较器
        public final Comparator<LossUserData> comparatorLevel = new Comparator<LossUserData>() {
            public int compare(LossUserData s1, LossUserData s2) {
                return s2.getLevel().compareTo(s1.getLevel());
            }
        };

        public Integer getLevel() {
            return level;
        }

        public void setLevel(Integer level) {
            this.level = level;
        }

        public String getLossType() {
            return lossType;
        }

        public void setLossType(String lossType) {
            this.lossType = lossType;
        }

        public int getAllLossUserNum() {
            return allLossUserNum;
        }

        public void setAllLossUserNum(int allLossUserNum) {
            this.allLossUserNum = allLossUserNum;
        }

        public int getLossUserNum() {
            return lossUserNum;
        }

        public void setLossUserNum(int lossUserNum) {
            this.lossUserNum = lossUserNum;
        }

        public int getOkUserNum() {
            return okUserNum;
        }

        public void setOkUserNum(int okUserNum) {
            this.okUserNum = okUserNum;
        }

        public float getLossRate() {
            return lossRate;
        }

        public void setLossRate(float lossRate) {
            this.lossRate = lossRate;
        }

        public float getLevelLossRate() {
            return levelLossRate;
        }

        public void setLevelLossRate(float levelLossRate) {
            this.levelLossRate = levelLossRate;
        }
    }


    public List<LossRoleSchoolData> getLossRoleSchoolDatas(Date date, String queryPlatform, String queryChannel, String queryServer) {
        List<LossRoleSchoolData> result = new ArrayList<>();

        List<Object[]> sumRoleNumberList = newRoleSchoolSecondLostLevelDistributeManager.getAllKindRoleNumber(date, queryPlatform, queryChannel, queryServer, GameParamConfigManager.ALL_FLAT);
        List<Object[]> levelList = newRoleSchoolSecondLostLevelDistributeManager.getKindRoleNumber(date, queryPlatform, queryChannel, queryServer);
        //总人数
        Integer sumRoleNumber = -1;
        if(sumRoleNumberList != null && sumRoleNumberList.size() > 0 && sumRoleNumberList.get(0)[0] != null) {
            Integer number = Integer.parseInt(sumRoleNumberList.get(0)[0].toString());
            sumRoleNumber = number == null ? sumRoleNumber : number;
        }

        for(Object[] o : levelList) {
            LossRoleSchoolData u = new LossRoleSchoolData();
            u.setLevel(Integer.parseInt(o[0].toString()));
            u.setSchool(Integer.parseInt(o[1].toString()));
            Integer role_number = Integer.parseInt(o[2].toString());
            u.setLossUserNum(role_number);
            u.setAllLossUserNum(sumRoleNumber);
            u.setLossRate(u.getAllLossUserNum() == 0 ? 0 : (float)(u.getLossUserNum() * 1.0 / u.getAllLossUserNum())) ;

            result.add(u);
        }

        Collections.sort(result, new LossRoleSchoolData().comparatorLevel);
        return result;
    }

    public class LossRoleSchoolData {
        @ChartFlow(name="等级")
        private Integer level;  // 等级
        private int school;  // 职业
        private String schoolStr;  // 职业名称
        private int allLossUserNum;  // 所有流失帐户数
        private int lossUserNum;  // 等级流失帐户数
        @ChartSelect(name = "等级职业流失", key = 1)
        @ChartData1(name = "流失人数占比", key = 1, multiByFiled = "schoolStr")
        private float lossRate;

        // 比较器
        public final Comparator<LostPlayerManager.LossRoleSchoolData> comparatorLevel = new Comparator<LostPlayerManager.LossRoleSchoolData>() {
            public int compare(LostPlayerManager.LossRoleSchoolData s1, LostPlayerManager.LossRoleSchoolData s2) {
                return s1.getLevel().compareTo(s2.getLevel());
            }
        };

        public Integer getLevel() {
            return level;
        }

        public void setLevel(Integer level) {
            this.level = level;
        }

        public int getSchool() {
            return school;
        }

        public void setSchool(int school) {
            this.school = school;
            this.schoolStr = GameParamConfigManager.getItemsRevise(CommonGameParam.SCHOOL).get(school + "") == null ? school + "" : GameParamConfigManager.getItemsRevise(CommonGameParam.SCHOOL).get(school + "");
        }

        public String getSchoolStr() {
            return schoolStr;
        }

        public void setSchoolStr(String schoolStr) {
            this.schoolStr = schoolStr;
        }

        public int getAllLossUserNum() {
            return allLossUserNum;
        }

        public void setAllLossUserNum(int allLossUserNum) {
            this.allLossUserNum = allLossUserNum;
        }

        public int getLossUserNum() {
            return lossUserNum;
        }

        public void setLossUserNum(int lossUserNum) {
            this.lossUserNum = lossUserNum;
        }

        public float getLossRate() {
            return lossRate;
        }

        public void setLossRate(float lossRate) {
            this.lossRate = lossRate;
        }
    }







    public List<LossRoleSchoolMainData> getLossRoleSchoolMainDatas(Date date, String queryPlatform, String queryChannel, String queryServer) {
        List<LossRoleSchoolMainData> result = new ArrayList<>();

        for (int i = 1; i <= 4; i++) {
            for (int j = 1; j <= 10; j++) {
                LossRoleSchoolMainData t = new LossRoleSchoolMainData();
                t.setSchool(i);
                t.setTask(j);
                t.setTaskSort(j);
                t.setJoinNum( + 500 + 500 * new Random().nextInt());
                t.setOkNum(j + 100 + 100 * new Random().nextInt());
                t.setOkPerJoinRate((float) Math.random());

                result.add(t);
            }
        }

        Collections.sort(result, new LossRoleSchoolMainData().comparatorLevel);

        return result;
    }

    public class LossRoleSchoolMainData {
        private int school;  // 职业
        private String schoolStr;  // 职业名称
        private int task;  // 任务
        @ChartFlow(name="任务")
        private String taskStr;  // 任务名称
        private Integer taskSort;  // 任务顺序
        private int joinNum;  // 所有流失帐户数
        private int okNum;  // 等级流失帐户数
        @ChartSelect(name = "完成率", key = 1)
        @ChartData1(name = "完成率", key = 1, multiByFiled = "schoolStr")
        private float okPerJoinRate;

        // 比较器
        public final Comparator<LostPlayerManager.LossRoleSchoolMainData> comparatorLevel = new Comparator<LostPlayerManager.LossRoleSchoolMainData>() {
            public int compare(LostPlayerManager.LossRoleSchoolMainData s1, LostPlayerManager.LossRoleSchoolMainData s2) {
                return  Integer.valueOf(s1.getSchool()).equals(Integer.valueOf(s2.getSchool())) ? s1.getTaskSort().compareTo(s2.getTaskSort()) : Integer.valueOf(s1.getSchool()).compareTo(Integer.valueOf(s2.getSchool()));
            }
        };

        public int getSchool() {
            return school;
        }

        public void setSchool(int school) {
            this.school = school;
            this.schoolStr = GameParamConfigManager.getItemsRevise(CommonGameParam.SCHOOL).get(school + "") == null ? school + "" : GameParamConfigManager.getItemsRevise(CommonGameParam.SCHOOL).get(school + "");
        }

        public String getSchoolStr() {
            return schoolStr;
        }

        public void setSchoolStr(String schoolStr) {
            this.schoolStr = schoolStr;
        }

        public int getTask() {
            return task;
        }

        public void setTask(int task) {
            this.task = task;
            this.taskStr = GameParamConfigManager.getItemsRevise(CommonGameParam.TASK_NAME).get(task + "") == null ? task + "" : GameParamConfigManager.getItemsRevise(CommonGameParam.TASK_NAME).get(task + "");
        }

        public String getTaskStr() {
            return taskStr;
        }

        public void setTaskStr(String taskStr) {
            this.taskStr = taskStr;
        }

        public Integer getTaskSort() {
            return taskSort;
        }

        public void setTaskSort(Integer taskSort) {
            this.taskSort = taskSort;
        }

        public int getJoinNum() {
            return joinNum;
        }

        public void setJoinNum(int joinNum) {
            this.joinNum = joinNum;
        }

        public int getOkNum() {
            return okNum;
        }

        public void setOkNum(int okNum) {
            this.okNum = okNum;
        }

        public float getOkPerJoinRate() {
            return okPerJoinRate;
        }

        public void setOkPerJoinRate(float okPerJoinRate) {
            this.okPerJoinRate = okPerJoinRate;
        }
    }
}
